package com.star.links.Service.Impl;

import android.content.Context;
import android.graphics.Point;
import android.util.Log;

import com.star.links.Service.PlayService;
import com.star.links.board.AbstractBoard;
import com.star.links.board.Impl.FullBoard;
import com.star.links.configure.PlayConfigure;
import com.star.links.views.Block;
import com.star.links.views.BlockImage;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class PlayServiceImpl implements PlayService {
    private Block[][] blocks;
    private PlayConfigure config;
    private boolean isConnect;
    private boolean path[][];

    public PlayServiceImpl(PlayConfigure config) {
        this.config = config;
    }

    @Override
    public void onStart() {
        // 定义一个AbstractBoard对象
        AbstractBoard board = null;
        board = new FullBoard();
        // 初始化Piece[][]数组
        this.blocks = board.create(config);
        path=new boolean[config.getColumnNum()][config.getRowNum()];
        isConnect=false;
    }

    @Override
    public Block[][] getBlocks() {
        return this.blocks;
    }


    @Override
    public boolean hasBlocks() {
        for (int i=0;i<blocks.length;i++){
            for (int j=0;j<blocks[i].length;j++){
                if(blocks[i][j]!=null)
                {
                    return true;
                }
            }
        }
        return false;
    }

    // 工具方法, 根据relative座标计算相对于Piece[][]数组的第一维
    // 或第二维的索引值 ，size为每张图片边的长或者宽
    private int getIndex(int relative, int size)
    {
        // 表示座标relative不在该数组中
        int index = -1;
        // 让座标除以边长, 没有余数, 索引减1
        // 例如点了x座标为20, 边宽为10, 20 % 10 没有余数,
        // index为1, 即在数组中的索引为1(第二个元素)
        if (relative % size == 0)
        {
            index = relative / size - 1;
        }
        else
        {
            //索引从0下表开始
            index = relative / size;
        }
        return index;
    }

    @Override
    public Block findBlock(float x, float y) {
            // 由于在创建Piece对象的时候, 将每个Piece的开始座标加了
            // GameConf中设置的beginImageX/beginImageY值, 因此这里要减去这个值
            int relativeX = (int) x - this.config.getFirstImageX();
            int relativeY = (int) y - this.config.getFirstImageY();

            // 如果鼠标点击的地方比board中第一张图片的开始x座标和开始y座标要小, 即没有找到相应的方块
            if (relativeX < 0 || relativeY < 0)
            {
                return null;
            }
            // 获取relativeX座标在Piece[][]数组中的第一维的索引值
            // 第二个参数为每张图片的宽
            int indexX = getIndex(relativeX, PlayConfigure.BLOCK_WIDTH);
            // 获取relativeY座标在Piece[][]数组中的第二维的索引值
            // 第二个参数为每张图片的高
            int indexY = getIndex(relativeY, PlayConfigure.BLOCK_HEIGHT);
            // 这两个索引比数组的最小索引还小, 返回null

            if (indexX < 0 || indexY < 0)
            {
                return null;
            }
            // 这两个索引比数组的最大索引还大(或者等于), 返回null
            if (indexX >= this.config.getColumnNum() || indexY >= this.config.getRowNum())
            {
                return null;
            }
            // 返回Piece[][]数组的指定元素
            return this.blocks[indexX][indexY];
        }

        @Override
        public void dfs(Point start, Point end)
        {
        int direction[][]=new int[][]{{0,-1},{0,1},{1,0}};
        for(int i=0; i<3; i++)
        {
            //深度搜索(x,y)
            int x=start.x+direction[i][0];
            int y=start.y+direction[i][1];
            if(x>=0&&x<config.getColumnNum()&&y>=0&&y<config.getRowNum())//满足条件
            {
                if(x==end.x&&y== end.y)//到达终点
                {
                    isConnect=true;
                    break;
                }
                else{
                    if(blocks[x][y]==null&&!path[x][y])
                    {
                        path[x][y]=true;
                        Point temp=new Point(x,y);
                        dfs(temp,end);
                        path[x][y]=false;
                    }
                }
            }
        }
    }

    private void DFSInit(){
        isConnect=false;
        for (int i=0;i< path.length;i++){
            for(int j=0;j<path[i].length;j++){
                path[i][j]=false;
            }
        }
    }

    /**
     * 判断两个方块是否可以连接
     * @param b1
     * @param b2
     * @return
     */
    @Override
    public boolean isLink(Block b1, Block b2) {

            // 两个Piece是同一个, 即选中了同一个方块, 返回null
            if (b1.equals(b2))
                return false;
            // 如果p1的图片与p2的图片不相同, 则返回null
            if (!b1.isSameImage(b2))
                return false;
            // 如果p2在p1的左边, 则需要重新执行本方法, 两个参数互换
            if (b2.getIndexX() < b1.getIndexX()) {
                Block blockTemp=b1;
                b1=b2;
                b2=blockTemp;
            }
            if (b1.getIndexY() == b2.getIndexY())
            {
                //判断两个方块之间是否有障碍
                if(b1.getIndexY()==0||b1.getIndexY()==config.getRowNum()-1||!isObstructedX(b1,b2)){
                    return true;
                }
            }
            // 如果两个Piece在同一列
            if (b1.getIndexX() == b2.getIndexX())
            {
                if(b1.getIndexX()==0||b1.getIndexX()==config.getColumnNum()-1||!isObstructedY(b1,b2)){
                    return true;
                }
            }

            DFSInit();
            Point p1=new Point(b1.getIndexX(),b1.getIndexY());
            Point p2=new Point(b2.getIndexX(),b2.getIndexY());
            dfs(p1,p2);
            return isConnect;

    }

    @Override
    public void reset() {
        List<BlockImage> temp=new ArrayList<>();
        for (int i=0;i<blocks.length;i++){
            for (int j=0;j<blocks[i].length;j++){
                if(blocks[i][j]!=null){
                    temp.add(blocks[i][j].getImage());
                }
            }
        }
        //重新洗牌
        Collections.shuffle(temp);
        //重新赋值
        int index=0;
        for(int i=0;i<blocks.length;i++){
            for (int j=0;j<blocks[i].length;j++){
                if(blocks[i][j]!=null){
                    blocks[i][j].setImage(temp.get(index));
                    index++;
                }
            }
        }
    }

    /**
     * 判断x方向上是否有阻碍
     * @param b1
     * @param b2
     * @return
     */
    private boolean isObstructedX(Block b1, Block b2){
        if (b2.getIndexX() < b1.getIndexX()) {
            Block blockTemp=b1;
            b1=b2;
            b2=blockTemp;
        }
        int i=b1.getIndexX()+1;
        int y=b1.getIndexY();
        for(;i<b2.getIndexX();i++)
        {
            if(blocks[i][y]!=null){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断Y方向上是否有阻碍
     * @param b1
     * @param b2
     * @return
     */
    private boolean isObstructedY(Block b1, Block b2){
        if (b2.getIndexY() < b1.getIndexY()) {
            Block blockTemp=b1;
            b1=b2;
            b2=blockTemp;
        }
        int i=b1.getIndexY()+1;
        int x=b1.getIndexX();
        for(;i<b2.getIndexY();i++)
        {
            if(blocks[x][i]!=null){
                return true;
            }
        }
        return false;
    }


}
